/**
 * 
 */
package ar.edu.utn.frsf.cidisi.ginet.generation.elementsestructure.elementstemplate;

import java.util.Map;

import org.eclipse.emf.common.util.EList;
import org.pnml.tools.epnk.pnmlcoremodel.AnnotationGraphics;
import org.pnml.tools.epnk.pnmlcoremodel.Coordinate;
import org.pnml.tools.epnk.pnmlcoremodel.Name;
import org.pnml.tools.epnk.pnmlcoremodel.PlaceNode;
import org.pnml.tools.epnk.pnmlcoremodel.PnmlcoremodelFactory;
import org.pnml.tools.epnk.pntypes.hlpng.pntd.hlpngdefinition.Declaration;
import org.pnml.tools.epnk.pntypes.hlpngs.datatypes.booleans.BooleansFactory;
import org.pnml.tools.epnk.pntypes.hlpngs.datatypes.integers.IntegersFactory;
import org.pnml.tools.epnk.pntypes.hlpngs.datatypes.terms.MultiSetSort;
import org.pnml.tools.epnk.pntypes.hlpngs.datatypes.terms.NamedSort;
import org.pnml.tools.epnk.pntypes.hlpngs.datatypes.terms.TermsFactory;
import org.pnml.tools.epnk.pntypes.hlpngs.datatypes.terms.UserSort;
import org.pnml.tools.epnk.pntypes.hlpngs.datatypes.terms.VariableDecl;

import ar.edu.utn.frsf.cidisi.ginet.abstractginet.Arc;
import ar.edu.utn.frsf.cidisi.ginet.abstractginet.Page;
import ar.edu.utn.frsf.cidisi.ginet.abstractginet.Place;
import ar.edu.utn.frsf.cidisi.ginet.abstractginet.RefPlace;
import ar.edu.utn.frsf.cidisi.ginet.abstractginet.Transition;
import ar.edu.utn.frsf.cidisi.ginet.generation.elementsestructure.NodeStructure;
import ar.edu.utn.frsf.cidisi.ginet.generation.elementsestructure.TreeInterface;
import ar.edu.utn.frsf.cidisi.upcolbpip.interactionprotocols.InteractionPath;
import ar.edu.utn.frsf.cidisi.upcolbpip.interactionprotocols.InteractionProtocolElement;

/**
 * @author Neri
 *
 */
public class OrUpcolbpipStructure extends ChoreographyStructure {
	
	public OrUpcolbpipStructure(Integer i){		
		super();		
		//Name		
		AnnotationGraphics graphicsName = PnmlcoremodelFactory.eINSTANCE
				.createAnnotationGraphics();
		
		Name nameLabel = PnmlcoremodelFactory.eINSTANCE.createName();
		
		Coordinate coordinate2 = PnmlcoremodelFactory.eINSTANCE.createCoordinate();
		
		coordinate2.setX(-9);
		coordinate2.setY( -39);
		
		graphicsName.setOffset(coordinate2);
		
		nameLabel.setText("OR" +i);
		nameLabel.setGraphics(graphicsName);
		
		this.abstractPage.setName(nameLabel);
	}
	
	@Override	
	public void createPageStructure(NodeStructure node, TreeInterface tree, PlaceNode placeIn, PlaceNode placeOut, EList<Declaration> ginetDeclarations, Place termination){		
		this.tree = tree;
		
		this.fillVarDeclAndNameSort(ginetDeclarations);
		
		Map<InteractionPath, EList<InteractionProtocolElement>> childrenCount = node.getChildrens();
		
		boolean whitRefPlaces = placeIn != null && placeOut != null;
		
		RefPlace refPlaceIn = null; 
		Place placeAndIn = null;
		if(whitRefPlaces){
			refPlaceIn = this.createRefPlace("InPlace",  1, 2, "InPlace", -4, -4, "1", placeIn);
		}else{
			placeAndIn = createPlace("InPlace", 1, 2, "InPlace", -4, -4, this.getVarDec("cond"), 6, 21, true, "1");
		}
		
		Transition transition1 = this.createTransition("xorit", 2, 2, "xorit", -4, -9, "1", "1", null);
		Arc arc1;
		if(whitRefPlaces){
			arc1 = this.createArc("", this.getVarDec("cond"), -37, -3, refPlaceIn, transition1);
		}else{
			arc1 = this.createArc("", this.getVarDec("cond"), -37, -3, placeAndIn, transition1);
		}

		Transition transition3 = this.createTransition("xorot", 6, 2, "ot", -9, -4, "1", "1", null);
		
		RefPlace refPlaceOut = null; 
		Place placeAndOut = null;
		Arc arc6;
		if(whitRefPlaces){
			refPlaceOut = this.createRefPlace("OutPlace", 7, 2, "OutPlace", -4, -4, "1", placeOut);
		}else{
			placeAndOut = createPlace("OutPlace", 7, 2, "OutPlace", -4, -4, this.getVarDec("cond"), 6, 21, false, "1");
		}
		
		if(whitRefPlaces){
			arc6 = this.createArc("", this.getVarDec("cond"), -9, -19, transition3, refPlaceOut);
		}else{
			arc6 = this.createArc("", this.getVarDec("cond"), -9, -19, transition3, placeAndOut);
		}
		
		int i = 1;
		
		for(InteractionPath inter: childrenCount.keySet()){
			
			Place place3 = createPlace("oripp"+ i, 3, i+1, "oripp"+ i,-9, -4 ,this.getVarDec("cond"), -4, -9, false, "1");			
			
			Place place4 = createPlace("oropp" + i, 5, i+1, "oropp"+ i,-9, -4 ,this.getVarDec("cond"), -4, -9, false, "1");
			
			this.createCondVariable(String.valueOf(i), ginetDeclarations);
			this.createCondVariable(i+"m", ginetDeclarations);
			
			if(inter.getElement().size() > 0){
				
				Page page = createPage("page" + i, 4, i+1, "page" + i, -9, -39);

				this.createInteractionProtocol(inter.getElement(), i, page, place3, place4, ginetDeclarations, termination);
			
				this.abstractPage.getObject().add(page);
				
			}else{				
				Transition transition2 = this.createTransition("oror" + i, 4, i+1, "or"+ i, -9, -39, "1", "1", null);
				Arc arc3 = this.createArc("", this.getVarDec("cond"+i, fillVarDecl(ginetDeclarations)), -19, -6, place3, transition2);
				Arc arc4 = this.createArc("", this.getVarDec("cond"+i, fillVarDecl(ginetDeclarations)), -9, -9, transition2, place4);
				this.abstractPage.getObject().add(transition2);
				this.abstractPage.getObject().add(arc3);
				this.abstractPage.getObject().add(arc4);
			}

			
			Arc arc2 = this.createArc("", this.getVarDec("cond"+i,fillVarDecl(ginetDeclarations)), -12, -8, transition1, place3);
			Arc arc5 = this.createArc("", this.getVarDec("cond"+i,fillVarDecl(ginetDeclarations)), -9, -9, place4, transition3);
			Arc arc7 = this.createArc("", 225, 210*i, 320, 210*i,this.getVarDec("cond"+i+"m", fillVarDecl(ginetDeclarations)), 100, -20, transition1, place4);
			
			this.abstractPage.getObject().add(place3);
			this.abstractPage.getObject().add(place4);

			this.abstractPage.getObject().add(arc2);
			this.abstractPage.getObject().add(arc5);
			this.abstractPage.getObject().add(arc7);
			
			i++;
		}

		if(whitRefPlaces){
			this.abstractPage.getObject().add(refPlaceIn);
			this.abstractPage.getObject().add(refPlaceOut);
		}else{			
			this.abstractPage.getObject().add(placeAndIn);
			this.abstractPage.getObject().add(placeAndOut);
		}
		
		this.abstractPage.getObject().add(transition1);
		this.abstractPage.getObject().add(transition3);
		
		this.abstractPage.getObject().add(arc1);
		this.abstractPage.getObject().add(arc6);		
	}

	/**
	 * @param i
	 *
	 * @author Neri
	 */
	private void createCondVariable(String i, EList<Declaration> ginetDeclarations) {
		if(this.getVarDec("cond" + i, fillVarDecl(ginetDeclarations)) == null){
			VariableDecl declVal = TermsFactory.eINSTANCE.createVariableDecl();
			
			UserSort userSort = TermsFactory.eINSTANCE.createUserSort();
			
			MultiSetSort multiSort = TermsFactory.eINSTANCE.createMultiSetSort();
			
			userSort.setDeclaration(this.getNamedSort("COND"));
			userSort.setName("COND");
			
			multiSort.setBasis(userSort);
			
			declVal.setId("cond" + i);
			declVal.setName("cond" + i);
			declVal.setSort(multiSort);
			
			ginetDeclarations.get(0).getStructure().getDeclaration().add(declVal);
			this.variableDecls.add(declVal);
		}
	}

}